package org.crud4j.ejb3;

import java.lang.reflect.Method;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Transient;

import org.crud4j.core.CrudBeanDef;
import org.crud4j.core.CrudFieldDef;
import org.crud4j.core.defprovider.CrudBeanDefProvider;

/**
 * Definition provider that reads JPA annotations to update the crud bean
 * definition
 */
public class Ejb3CrudBeanDefProvider implements CrudBeanDefProvider {

	/**
	 * Updates the crud bean definition according to jpa annotations
	 */
	public void updateDef(Class type, CrudBeanDef crudBeanDef) {

		for (Method m : type.getMethods()) {
			// filter only getter methods
			// FIXME check other methods ?
			if (m.getName().startsWith("get")
					&& !m.getName().equals("getClass")) {

				// field Name
				String firstChar = m.getName().substring(3).substring(0, 1);
				firstChar = firstChar.toLowerCase();
				String fieldName = firstChar + m.getName().substring(4);

				CrudFieldDef fieldDef = crudBeanDef.getFieldDef(fieldName);

				if (fieldDef == null) {
					continue;
				}

				// transient annotation
				if (m.isAnnotationPresent(Transient.class)) {
					fieldDef.setEditDisabled(true);
					fieldDef.setNewDisabled(true);
				}

				// Id annotation
				if (m.isAnnotationPresent(Id.class)) {
					fieldDef.setId(true);
					fieldDef.setNullable(false);
				}

				// generated value annotation
				if (m.isAnnotationPresent(GeneratedValue.class)) {
					fieldDef.setEditDisabled(true);
					fieldDef.setNewDisabled(true);
					fieldDef.setGeneratedValue(true);
				}

				// Column annotation
				if (m.isAnnotationPresent(Column.class)) {
					Column c = m.getAnnotation(Column.class);

					fieldDef.setNullable(c.nullable());
					fieldDef.setEditDisabled(!c.updatable());
					fieldDef.setNewDisabled(!c.insertable());

					if (c.length() > 0) {
						fieldDef.setLength(c.length());
					}
				}

				// Join column annotation
				if (m.isAnnotationPresent(JoinColumn.class)) {
					JoinColumn c = m.getAnnotation(JoinColumn.class);
					fieldDef.setNullable(c.nullable());
				}

			}
		}

	}
}
